using System;
using System.Collections.Generic;
using System.Text;
using EnvDTE;
using System.Diagnostics;
using System.IO;
using wscf.lightblue;
using VsWebSite;
using VSLangProj80;

namespace wscf_lightblue_VSAddIn
{
	/// <summary>
	/// Represents a project in Visual Studio
	/// </summary>
	public class VisualStudioProject
	{
		#region Private Fields

		private Project project;

		#endregion

		#region Public Constructors

		/// <summary>
		/// Initializes a new instance of the <see cref="VisualStudioProject"/> class.
		/// </summary>
		/// <param name="project">The project.</param>
		public VisualStudioProject(Project project)
		{
			this.project = project;
		}

		#endregion

		#region Public Properties

		/// <summary>
		/// Gets the name of the project file.
		/// </summary>
		/// <value>
		/// The name of the project file.
		/// </value>
		public string ProjectFileName
		{
			get { return this.project.FileName; }
		}

		/// <summary>
		/// Gets a value indicating whether this instance is web project.
		/// </summary>
		/// <value>
		/// 	<c>true</c> if this instance is web project; otherwise, <c>false</c>.
		/// </value>
		public bool IsWebProject
		{
			get { return this.project.Object is VSWebSite; }
		}

		/// <summary>
		/// Gets the project language.
		/// </summary>
		public ClrLanguage ProjectLanguage
		{
			get
			{
				return (IsWebProject) ? GetWebProjectLanguage() : GetProjectLanguage();
			}
		}

		/// <summary>
		/// Gets the assembly namespace.
		/// </summary>
		public string AssemblyNamespace
		{
			get
			{
				return this.project.Properties.Item("DefaultNamespace").Value.ToString();
			}
		}

		/// <summary>
		/// Gets the project directory.
		/// </summary>
		public string ProjectDirectory
		{
			get
			{
				return this.project.Properties.Item("FullPath").Value.ToString();
			}
		}

		private string AssemblyName
		{
			get
			{
				return project.Properties.Item("AssemblyName").Value.ToString();
			}
		}

		#endregion

		#region Public Methods

		/// <summary>
		/// Adds the file.
		/// </summary>
		/// <param name="file">The file.</param>
		public void AddFile(string file)
		{
			Debug.Assert(File.Exists(file), "Attemp to add a non-existing file.");
			this.project.ProjectItems.AddFromFile(file);
			this.Refresh();
		}

		/// <summary>
		/// Adds the code folder to web project.
		/// </summary>
		/// <param name="name">The name.</param>
		/// <returns></returns>
		public string AddCodeFolderToWebProject(string name)
		{
			Debug.Assert(this.IsWebProject, "Cannot add code folders to a web project.");
			VSWebSite website = (VSWebSite)project.Object;
			string relativePath = string.Format(@"App_Code/{0}", name);
			website.CodeFolders.Add(relativePath);

			CodeFolder appCodeFolder = website.CodeFolders.Item(1);
			return Path.Combine(appCodeFolder.ProjectItem.get_FileNames(0), name);
		}

		/// <summary>
		/// Adds the reference.
		/// </summary>
		/// <param name="assembly">The assembly.</param>
		public void AddReference(string assembly)
		{
			if (IsWebProject)
			{
				VSWebSite website = this.project.Object as VSWebSite;
				website.References.AddFromGAC(assembly);
			}
			else
			{
				VSProject2 prj = this.project.Object as VSProject2;
				prj.References.Add(assembly);
			}
		}

		/// <summary>
		/// Gets the referenced assemblies.
		/// </summary>
		/// <returns></returns>
		public List<string> GetReferencedAssemblies()
		{
			List<string> referencedAssemblies = new List<string>();
			if (IsWebProject)
			{
				VSWebSite website = this.project.Object as VSWebSite;
				if (website != null)
				{
					foreach (Reference3 r in website.References)
					{
						referencedAssemblies.Add(r.Path);
					}
				}
			}
			else
			{
				VSProject2 prj = this.project.Object as VSProject2;
				if (prj != null)
				{
					foreach (Reference3 r in prj.References)
					{
						referencedAssemblies.Add(r.Path);
					}
				}
			}
			return referencedAssemblies;
		}

		#endregion

		#region Private Methods

		private ClrLanguage GetWebProjectLanguage()
		{
			string language = this.project.Properties.Item("CurrentWebSiteLanguage").Value.ToString();

			switch (language)
			{
				case "Visual Basic":
					return ClrLanguage.vb;
				case "Visual C#":
					return ClrLanguage.cs;
				default:
					return ClrLanguage.cs;
			}
		}

		private ClrLanguage GetProjectLanguage()
		{
			switch (project.Kind)
			{
				case VSLangProj_PrjKind.prjKindVBProject:
					return ClrLanguage.vb;
				case VSLangProj_PrjKind.prjKindCSharpProject:
					return ClrLanguage.cs;
				default:
					return ClrLanguage.cs;
			}
		}

		private bool Refresh()
		{
			if (IsWebProject)
			{
				VSWebSite website = this.project.Object as VSWebSite;
				if (website != null)
				{
					website.Refresh();
					return true;
				}
			}
			else
			{
				VSProject2 project = this.project.Object as VSProject2;
				if (project != null)
				{
					project.Refresh();
					return true;
				}
			}
			return false;
		}

		#endregion
	}
}
